package com.cv.system.service.auth;

import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.cv.framework.common.enums.CommonStatusEnum;
import com.cv.framework.common.enums.UserTypeEnum;
import com.cv.framework.common.utils.servlet.ServletUtil;
import com.cv.framework.common.utils.validation.ValidationUtil;
import com.cv.framework.security.core.utils.JwtUtil;
import com.cv.system.api.token.form.LoginUser;
import com.cv.system.controller.audit.auth.vo.AuditAuthLoginReqVO;
import com.cv.system.controller.audit.auth.vo.AuditAuthLoginRespVO;
import com.cv.system.controller.system.role.vo.RoleRespVO;
import com.cv.system.dal.dataobject.user.SystemUsersDO;
import com.cv.system.enums.logger.LoginLogTypeEnum;
import com.cv.system.enums.role.RoleCodeEnum;
import com.cv.system.service.role.SystemRoleService;
import com.cv.system.service.user.SystemUserService;
import com.google.common.annotations.VisibleForTesting;
import com.xingyuv.captcha.model.common.ResponseModel;
import com.xingyuv.captcha.model.vo.CaptchaVO;
import com.xingyuv.captcha.service.CaptchaService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import javax.validation.Validator;

import static com.cv.framework.common.exception.utils.ServiceExceptionUtil.exception;
import static com.cv.system.ErrorCodeConstants.*;

/**
 * 客服审核平台认证业务层接口实现类
 *
 * @author Charles_XDXD
 */
@Service
@Slf4j
@Validated
public class AuditAuthServiceImpl implements AuditAuthService {

    @Resource
    private SystemUserService systemUserService;

    @Resource
    private CaptchaService captchaService;

    @Resource
    private Validator validator;

    @Resource
    private SystemRoleService systemRoleService;

    @Value("${cv.captcha.enable:true}")
    private Boolean captchaEnable;

    @Override
    public SystemUsersDO authenticate(String username, String password) {
        SystemUsersDO user = systemUserService.getUserByUsername(username);

        // 校验用户是否存在
        if (ObjUtil.isEmpty(user)) {
            throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
        }

        // 校验登录密码
        if (!systemUserService.isPasswordMatch(password, user.getPassword())) {
            throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
        }

        // 校验是否禁用
        if (CommonStatusEnum.isDisable(user.getStatus())) {
            throw exception(AUTH_LOGIN_USER_DISABLED);
        }

        // 校验用户权限
        RoleRespVO userRole = systemRoleService.getUserRoleByUserId(user.getId());
        if (ObjUtil.isEmpty(userRole)) {
            throw exception(AUTH_LOGIN_USER_UNAUTHORIZED);
        }

        if (!StrUtil.equalsAny(userRole.getCode(),
                RoleCodeEnum.CUSTOMER_SERVICE.getCode(),
                RoleCodeEnum.AUDIT_ADMIN.getCode())) {
            throw exception(AUTH_LOGIN_USER_UNAUTHORIZED);
        }

        return user;
    }

    @Override
    public AuditAuthLoginRespVO login(AuditAuthLoginReqVO reqVO) {
        // 校验验证码
        validateCaptcha(reqVO);

        // 使用账号密码登录
        SystemUsersDO user = authenticate(reqVO.getUsername(), reqVO.getPassword());

        // 创建令牌
        return createTokenAfterLoginSuccess(user.getId());
    }

    @Override
    public void logout(String token, LoginLogTypeEnum loginLogTypeEnum) {
        // 预留功能位置，暂时什么事都不做，后续有需求再添加功能
        if (ObjUtil.isNotEmpty(token)) {
            JwtUtil.parseToken(token);
        }
    }

    @VisibleForTesting
    void validateCaptcha(AuditAuthLoginReqVO reqVO) {
        // 如果验证码关闭，则不进行校验
        if (!captchaEnable) {
            return;
        }

        // 校验验证码
        ValidationUtil.validate(validator, reqVO, AuditAuthLoginReqVO.CodeEnableGroup.class);
        CaptchaVO captchaVO = new CaptchaVO();
        captchaVO.setCaptchaVerification(reqVO.getCaptchaVerification());
        ResponseModel response = captchaService.verification(captchaVO);

        // 验证不通过
        if (!response.isSuccess()) {
            throw exception(AUTH_LOGIN_CAPTCHA_CODE_ERROR, response.getRepMsg());
        }
    }

    /**
     * 创建令牌
     *
     * @param userId 用户编号
     * @return 令牌
     */
    private AuditAuthLoginRespVO createTokenAfterLoginSuccess(Long userId) {
        LoginUser loginUser = new LoginUser().setId(userId).setUserType(UserTypeEnum.ADMIN.getValue());
        RoleRespVO userRoleByUserId = systemRoleService.getUserRoleByUserId(userId);

        if (ObjUtil.isNotEmpty(userRoleByUserId)) {
            loginUser.setRoleId(userRoleByUserId.getId());
            loginUser.setRoleName(userRoleByUserId.getCode());
        }

        // 更新当前登录的 ip 和时间
        systemUserService.updateLoginIpAndTime(userId, ServletUtil.getClientIP());

        String token = JwtUtil.createToken(loginUser);
        return new AuditAuthLoginRespVO(userId, token);
    }

}
